package mini.compiler;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Writer;

import mini.Program;

public class Optimizer {

	public Optimizer() {
	}

	/**
	 * Don't worry about opening or closing the readers/writers, that's done elsewhere.
	 * 
	 * @param memReader A reader that points to a newline-delimited set of linked
	 * RAL memory, something like resources/sample_mem.txt
	 * @param progReader A reader that points to a newline-delimited set of linked
	 * RAL instructions, something like resources/sample_prog.txt
	 * @param memoryWriter Should look something like resources/sample_mem.txt but
	 * work with whatever optimized RAL instructions are written to the programWriter
	 * @param programWriter Should look something like resources/sample_program.txt
	 * but should be optimized with peephole optimization (see slides 24-25 of the
	 * set at https://www.cs.drexel.edu/~jjohnson/2011-12/spring/cs550/lectures/compiler.pdf
	 */
	public void optimize( BufferedReader progReader, Writer programWriter ) {
		
		/**
		 * This is just some placeholder code for now. It just prepends a line to the linked code and memory.
		 */
	
		try {
			//programWriter.write( "Pretend this is program instructions in an optimized and linked RAL format for the following:" + Program.NEWLINE + Program.NEWLINE);
			String line = progReader.readLine();
			
			String[] currLine = null;
			String[] keptLine = null;
			boolean wasStore = false;
			int count_preOpt = 0;
			int count_postOpt = 0;
						
			while( line != null ) {
				count_preOpt++;
				
				currLine = line.split(" ");
				
				if(currLine[0].contains("STA")){
					wasStore = true;
					keptLine = currLine;
				}
				

				if(wasStore){
					String command="";
					String operand1="";
					String operand2="";
					
					if(currLine.length==2){
						command=currLine[0];
						operand1=currLine[1];
					}else if(currLine.length==3){
						command = currLine[1];
						operand1=currLine[2];
					}
				
					if(keptLine.length==2){
						operand2=keptLine[1];
					}else if(keptLine.length==3){
						operand2=keptLine[2];
					}
					
					if(command.equals("STA")){
						wasStore = true;
						keptLine = currLine;
					}else{
						wasStore = false;
						try{
							//I think we only car about lda optimizations after a store...
							if(operand1.equals(operand2) && !currLine[0].contains(":") && line.contains("LDA")) {
								line = null;
							}
						}catch (ArrayIndexOutOfBoundsException e){
							System.out.println("Line did not have 2 elements. Continuing but there will be errors.");
						}catch (Exception e){
							System.out.println("Continuing but there are errors. Random exception: " +e);
						}
					}
				}

				if( line != null){
					count_postOpt++;
					programWriter.write(line);
					programWriter.write( Program.NEWLINE );
				}
				
				line = progReader.readLine();
			}
			
			System.out.println("Pre optimizer line count: " + count_preOpt + " Post optimizer line count: " + count_postOpt);
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
